package com.dq.controller.sys;

import com.alibaba.fastjson.JSONObject;
import com.dq.annotation.aop.SysLog;
import com.dq.cache.J2CacheUtils;
import com.dq.context.Constant;
import com.dq.exception.customException.AdminException;
import com.dq.controller.AbstractController;
import com.dq.controller.op.opmerchant.in.query.SysMenuQuery;
import com.dq.vo.ListVo;
import com.dq.vo.Vo;
import com.dq.vo.baseVo.VO;
import com.dq.domain.sys.menu.NullSysMenu;
import com.dq.domain.sys.menu.SysMenu;
import com.dq.domain.sys.role.SysUserRole;
import com.dq.domain.sys.user.user.BossUser;
import com.dq.domain.sys.user.user.OrgUser;
import com.dq.domain.sys.user.user.StaffUser;
import com.dq.domain.sys.user.user.base.SysUser;
import com.dq.utils.BeanNullUtil;
import com.dq.utils.TreeBuilder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 系统菜单
 *
 * @author lipengjun
 * @email 939961241@qq.com
 * @date 2016年10月27日 下午9:58:15
 */
@Api(description = "后台菜单管理")
@RestController
@RequestMapping("/sys/menu")
public class SysMenuController extends AbstractController {
    /**
     * 非admin只获取自己创建的菜单
     */
    @ApiOperation("菜单列表-分页-非树形列表")
    @PostMapping("/list")
    @RequiresPermissions("sys:menu:list")
    public ListVo<SysMenu> list(@RequestBody SysMenuQuery menuQuery) throws AdminException {
        if(menuQuery.getGenre() == null) {
            throw new AdminException("参数异常, 选择获取平台或门店菜单");
        }
        //查询列表数据
        Map<String, Object> query = menuQuery.parseMap();
        if (shiroService.isSuperAdmin()) {
            List<SysMenu> menuList = dao.find(dao.queryAdminHql(SysMenu.class, query), query);
            Long total = dao.count(dao.countAdminHql(SysMenu.class, query), query);
            return new ListVo(menuList, total);
        } else {
            List<SysMenu> menuList = sysUserService.findAllByUser(shiroService.getUser());
            Long total = sysUserService.countAllByUser(shiroService.getUser());
            return new ListVo(menuList, total);
        }
    }
    /**
     * 非admin只获取自己创建的菜单
     */
    @ApiOperation("菜单列表-不分页-非树形列表")
    @GetMapping("/queryAll")
    public Vo<SysMenu.Vo> queryAll(@RequestBody SysMenuQuery sysMenuQuery) throws AdminException {
        if(sysMenuQuery.getGenre() == null) {
            throw new AdminException("参数异常, 选择获取平台或门店菜单");
        }
        List<SysMenu> menuList = new ArrayList<>();
        if (shiroService.isSuperAdmin()) {
            menuList = sysMenuRepository.findByDeletedIsFalseAndGenreOrderByOrderNumAsc(sysMenuQuery.getGenre());
        } else {
            menuList = sysUserService.findAllByUser(shiroService.getUser());
        }
        return new ListVo((List<SysMenu.Vo>) VO.toVOCollection(menuList));
    }

    @ApiOperation("所有菜单-树形列表")
    @PostMapping("/listTreeMenu")
    public Vo<SysMenu.Vo> listTreeMenu() throws AdminException {
        List<SysMenu> sysMenus = new ArrayList<>();

        boolean isAdmin = false;
        SysUser user = sysUserService.getUser();
        SysMenu.Genre genre = null;
        if(user instanceof BossUser) {
            genre = SysMenu.Genre.boss;
        }else if(user instanceof OrgUser || user instanceof StaffUser) {
            genre = SysMenu.Genre.org;
        }

        List<SysUserRole> bySysUser = sysUserRoleRepository.findBySysUser(user);
        for (SysUserRole userRole : bySysUser) {
            if(Constant.ROLE_CODE_LIST.get(0).equals(userRole.getSysRole().getCode())) {
                isAdmin = true;
                break;
            }
        }
        if (isAdmin || String.valueOf(Constant.ADMIN_ID).equals(user.getId().toString()) || user instanceof OrgUser) {
            sysMenus = sysMenuRepository.findByDeletedIsFalseAndGenreOrderByOrderNumAsc(genre);
        } else {
            sysMenus = sysUserService.findAllByUser(shiroService.getUser());
        }
        Set<SysMenu.Vo> sysMenuSet = new HashSet<>();
        sysMenus.forEach(sysMenu -> {
            sysMenuSet.add((SysMenu.Vo) sysMenu.toVO(false));
        });
        List<SysMenu.Vo> sysMenuVo = TreeBuilder.buildTree(sysMenuSet);
        JSONObject json = new JSONObject();
        json.put("menuList", sysMenus);
        json.put("menuTree", sysMenuVo);
        return new Vo(json);
    }

    /**
     * 选择菜单(添加、修改菜单)
     */
    @ApiOperation("选择菜单(添加、修改菜单)")
    @GetMapping("/select")
    @RequiresPermissions("sys:menu:select")
    public Vo<SysMenu.Vo> select(@RequestBody SysMenuQuery sysMenuQuery) throws AdminException {
        if(sysMenuQuery.getGenre() == null) {
            throw new AdminException("参数异常");
        }
        //查询列表数据
        List<SysMenu> menuList = sysMenuRepository.findByDeletedIsFalseAndGenreAndTypeIsNotAndStatus(sysMenuQuery.getGenre(), SysMenu.Type.button, SysMenu.Status.on);

        List<SysMenu.Vo> sysMenuVos = (List<SysMenu.Vo>) VO.toVOCollection(menuList);
        return new ListVo(sysMenuVos);
    }

    /**
     * 角色授权菜单
     */
    @ApiOperation("角色授权菜单")
    @GetMapping("/perms")
    @RequiresPermissions("sys:menu:perms")
    public Vo<SysMenu.Vo> perms() throws AdminException {
        SysUser user = sysUserService.getUser();
        SysMenu.Genre genre = null;
        if(user instanceof BossUser) {
            genre = SysMenu.Genre.boss;
        }else if(user instanceof OrgUser || user instanceof StaffUser) {
            genre = SysMenu.Genre.org;
        }

        //查询列表数据
        List<SysMenu.Vo> sysMenuVo;
        //只有超级管理员，才能查看所有管理员列表
        if (user.getId() == Constant.ADMIN_ID) {
            sysMenuVo = (List<SysMenu.Vo>) VO.toVOCollection(sysMenuRepository.findByDeletedIsFalseAndGenreAndStatus(genre, SysMenu.Status.on));
        } else {
            sysMenuVo = (List<SysMenu.Vo>) VO.toVOCollection(sysMenuService.findBySysUserAndStatus(getUser(), SysMenu.Status.on));
        }

        return new ListVo(sysMenuVo);
    }

    /**
     * 菜单信息
     */
    @ApiOperation("菜单信息")
    @GetMapping("/info/{menuId}")
    @RequiresPermissions("sys:menu:info")
    public Vo<SysMenu> info(@PathVariable @ApiParam(value = "菜单id") Long menuId) {
        SysMenu menu = dao.get(SysMenu.class, menuId);
        return new Vo(menu.toVO());
    }

    /**
     * 保存
     */
    @ApiOperation("保存菜单")
    @SysLog("保存菜单")
    @PostMapping("/save/{parentMenuId}")
    @RequiresPermissions("sys:menu:save")
    public Vo save(@RequestBody SysMenu menu, @PathVariable @ApiParam(value = "父级菜单id") Long parentMenuId) throws AdminException {
        if (parentMenuId == null || parentMenuId == 0) {
            menu.setParent((NullSysMenu) J2CacheUtils.get("NullSysMenu"));
        } else {
            SysMenu sysParentMenu = dao.get(SysMenu.class, parentMenuId);
            if (null == sysParentMenu) {
                throw new AdminException("无效的父级菜单");
            }
            menu.setParent(sysParentMenu);
        }

        //数据校验
        verifyForm(menu);

        if(menu.getStatus() == null) {
            menu.setStatus(SysMenu.Status.on);
        }

        sysMenuRepository.save(menu);
        return new Vo(HttpStatus.OK);
    }

    /**
     * 修改
     */
    @ApiOperation("修改菜单")
    @SysLog("修改菜单")
    @PostMapping("/update/{menuId}")
    @RequiresPermissions("sys:menu:update")
    public Vo update(@RequestBody SysMenu menu, @PathVariable @ApiParam(value = "菜单id") Long menuId) throws AdminException {
        SysMenu sysMenu = dao.get(SysMenu.class, menuId);
        if (sysMenu == null) {
            throw new AdminException("菜单不存在");
        }
        BeanUtils.copyProperties(menu, sysMenu, BeanNullUtil.getNullPropertyNames(menu));
        sysMenuRepository.save(sysMenu);
        return new Vo(HttpStatus.OK);
    }

    /**
     * 删除
     */
    @ApiOperation("删除")
    @SysLog("删除菜单")
    @PostMapping("/delete/{menuId}")
    @RequiresPermissions("sys:menu:delete")
    public Vo delete(@PathVariable @ApiParam(value = "菜单id") Long menuId) throws AdminException {
        SysMenu sysMenu = dao.get(SysMenu.class, menuId);
        List<SysMenu> sysMenus = sysMenuRepository.findByParentAndDeletedFalse(sysMenu);
        if (!sysMenus.isEmpty()) {
            throw new AdminException("请先删除子菜单");
        }
        sysMenuService.deleteBath(sysMenu);
        return new Vo(HttpStatus.OK);
    }

    /**
     * 用户菜单列表
     */
    @ApiOperation("用户菜单列表")
    @GetMapping("/user")
    public Vo<SysMenu.Vo> user() {
        List<SysMenu> menuList = sysMenuService.findBySysUserAndStatus(getUser(), SysMenu.Status.on);
        return new Vo(VO.toVOCollection(menuList));
    }

    /**
     * 验证参数是否正确
     */
    private void verifyForm(SysMenu menu) throws AdminException {
        if(menu.getGenre() == null) {
            throw new AdminException("菜单所属平台或门店为空");
        }
        if (StringUtils.isBlank(menu.getTitle())) {
            throw new AdminException("菜单名称不能为空");
        }

        if (menu.getParent() == null) {
            throw new AdminException("上级菜单不能为空");
        }

        //菜单
        if (menu.getType().equals(SysMenu.Type.param)) {
            if (StringUtils.isBlank(menu.getResources())) {
                throw new AdminException("菜单URL不能为空");
            }
        }

        //上级菜单类型
        SysMenu.Type parentType = SysMenu.Type.list;
        if (menu.getParent() != null) {
            SysMenu parentMenu = menu.getParent();
            parentType = parentMenu.getType();
        }

        //目录、菜单
        if (menu.getType().equals(SysMenu.Type.list) ||
                menu.getType().equals(SysMenu.Type.param)) {
            if (!parentType.equals(SysMenu.Type.list)) {
                throw new AdminException("上级菜单只能为目录类型");
            }
            return;
        }

        //按钮
        if (menu.getType().equals(SysMenu.Type.button)) {
            if (!parentType.equals(SysMenu.Type.param)) {
                throw new AdminException("上级菜单只能为菜单类型");
            }
            return;
        }
    }
}
